home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1997 October: Mac OS SDK / Dev.CD Oct 97 SDK1.toast / Development Kits (Disc 1) / QuickDraw GX / Programming Stuff / GXEdit Library & Doc / GXEditReplace.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-04-10  |  7.8 KB  |  304 lines  |  [TEXT/MPS ]

  1. #include "GXEdit.h"
  2. #include "GXEditDoc.h"
  3. #include "GXEditReplace.h"
  4. #include "GXEditNewRun.h"
  5. #include "GXEditDebug.h"
  6. #include "GXEditStyle.h"
  7.  
  8. static void     InitCounters(ReplacementPtr replacements);
  9. static void     IncrementCounters(ReplacementPtr replacements);
  10. static void     FindAndAdd(ReplacementPtr replacements);
  11. static void    AddReplace(ReplacementPtr replacements, ReplacePtr replace);
  12. static Boolean    FindReplace(ReplacementPtr replacements, short replaceIndex, ReplacePtr replace);
  13. static Boolean    FindStrInRun(ReplacementPtr replacements, Str255 str, NewRunPtr rp, short *runOffset);
  14. static void    DoReplace(ReplacementPtr replacements, ReplacePtr replace);
  15.  
  16. void    NewReplacements(DocPtr dp, GXEditProofPtr proof, ReplacementPtr replacements)
  17. {
  18.     replacements->dp = dp;
  19.     replacements->proof = proof;
  20.     replacements->numReplacements = 0;
  21.     replacements->replaceList = (ReplaceHan) NewHandle(0);
  22.     
  23.     FindAndAdd(replacements);
  24.     
  25.     InitCounters(replacements);
  26. }
  27.  
  28. void    DoReplacements(ReplacementPtr replacements)
  29. {
  30.     short        i;
  31.     ReplacePtr    rp;
  32.     
  33.     rp = *replacements->replaceList;
  34.     
  35.     for(i=0; i<replacements->numReplacements; i++, rp++)
  36.         DoReplace(replacements, rp);
  37.  
  38.     IncrementCounters(replacements);
  39.     
  40. }
  41.  
  42. Boolean TestReplacements(ReplacementPtr replacements)
  43. {
  44.     if(replacements->done) {
  45.         replacements->done = false;
  46.         return(true);
  47.     } else
  48.         return(false);
  49.         
  50. }
  51.  
  52. void    DisposeReplacements(ReplacementPtr replacements)
  53. {
  54.     DisposeHandle((Handle) replacements->replaceList);
  55. }
  56.  
  57. static void InitCounters(ReplacementPtr replacements)
  58. {
  59.     short        i;
  60.     
  61.     for(i=0; i<kGXEditNumReplace && replacements->proof->replace[i]; i++)
  62.         replacements->curChar[i] = replacements->proof->fromChar[i];
  63.     
  64.     replacements->done = false;
  65. }
  66.  
  67. static void IncrementCounters(ReplacementPtr replacements)
  68. {
  69.     short        i;
  70.     
  71.     for(i=0; i<kGXEditNumReplace && replacements->proof->replace[i]; i++)
  72.         if(replacements->curChar[i] < replacements->proof->toChar[i]) {
  73.             replacements->curChar[i]++;
  74.             return;
  75.         } else
  76.             replacements->curChar[i] = replacements->proof->fromChar[i];
  77.     
  78.     replacements->done = true;
  79.     
  80. }
  81.  
  82. static void FindAndAdd(ReplacementPtr replacements)
  83. {
  84.     short        i,j;
  85.     ReplaceRec    replace;
  86.     
  87.     for(i=0; i<kGXEditNumReplace && replacements->proof->replace[i]; i++)
  88.         while(FindReplace(replacements, i, &replace)) {
  89.         
  90.             AddReplace(replacements, &replace);
  91.             
  92.             /* now adjust any replacements whose run offsets was affected when
  93.                the replacement was made */
  94.             
  95.             for(j=0; j<(replacements->numReplacements - 1); j++)
  96.                 if((*replacements->replaceList)[j].runIndex == replace.runIndex &&
  97.                    (*replacements->replaceList)[j].runOffset > replace.runOffset)
  98.                    (*replacements->replaceList)[j].runOffset -= replacements->proof->replaceStr[i][0] - 1;
  99.                        
  100.         }
  101.     
  102. }
  103.  
  104. static void AddReplace(ReplacementPtr replacements, ReplacePtr replace)
  105. {
  106.     replacements->numReplacements++;
  107.     PtrAndHand((Ptr) replace, (Handle) replacements->replaceList, sizeof(ReplaceRec));
  108. }
  109.  
  110. static Boolean FindReplace(ReplacementPtr replacements, short replaceIndex, ReplacePtr replace)
  111. {
  112.     ScrapPtr            scrap;
  113.     NewRunPtr        rp;
  114.     short            charsToRemove;
  115.     short            runIndex;
  116.     short            runOffset;
  117.     short            styleIndex;
  118.     DocPtr            dp;
  119.     Size                size;
  120.  
  121.     dp = replacements->dp;
  122.     
  123.     scrap = &replacements->dp->scrap;
  124.     
  125.     HLock((Handle) scrap->runs);
  126.     
  127.     rp = *scrap->runs;
  128.     
  129.     for(runIndex = 0; runIndex < scrap->numRuns; runIndex++, rp++)
  130.         if(FindStrInRun(replacements, replacements->proof->replaceStr[replaceIndex], rp, &runOffset)) {
  131.         
  132.             if(!replacements->proof->glyphIndicies) {
  133.             
  134.                 /* remove all but one character of replacement string */
  135.                 
  136.                 charsToRemove = replacements->proof->replaceStr[replaceIndex][0] - 1;
  137.                 
  138.                 if(charsToRemove > 0) {
  139.                     NewRunClear(dp, rp, runOffset + 1, charsToRemove);
  140.                     scrap->numText -= charsToRemove;
  141.                 }
  142.                 
  143.             } else {
  144.             
  145.                 /* hmm, lets see.  Since we were able to find the string, the run must not have
  146.                      the platform of gxGlyphPlatform.  So, we will need to delete the replace string
  147.                      and insert a new run with a single dummy glyph index and an appropriate encoding */
  148.                      
  149.                 styleIndex = SetDocStyleEncoding(replacements->dp, rp->styleIndex, gxGlyphPlatform, gxNoScript, gxNoLanguage);
  150.                      
  151.                 /* lets first delete the replace string */
  152.                 
  153.                 charsToRemove = replacements->proof->replaceStr[replaceIndex][0];
  154.                 NewRunClear(dp, rp, runOffset, charsToRemove);
  155.                 
  156.                 scrap->numText -= charsToRemove;
  157.  
  158.                 /* now, insert the dummy glyph index
  159.                      NOTE: if you get a feeling of DejaVu, look at GXEditParagraph text insertion */
  160.                 
  161.                 if(runOffset == 0) {
  162.                 
  163.                     scrap->numRuns++;
  164.                     
  165.                     HUnlock((Handle) scrap->runs);
  166.                     
  167.                     size = scrap->numRuns * sizeof(NewRunRec);
  168.                     SetHandleSize((Handle) scrap->runs, size);
  169.                     
  170.                     HLock((Handle) scrap->runs);
  171.                     
  172.                     size = (scrap->numRuns - runIndex - 1) * sizeof(NewRunRec);
  173.                     BlockMove((Ptr) (*scrap->runs + runIndex), (Ptr) (*scrap->runs + runIndex + 1), size);
  174.                     
  175.                     NewNewRun(dp, *scrap->runs + runIndex, styleIndex);
  176.                     
  177.                     runOffset = 0;
  178.                     
  179.                 } else if(runOffset == rp->numText) {
  180.                 
  181.                     runIndex++;
  182.                     
  183.                     scrap->numRuns++;
  184.                     
  185.                     HUnlock((Handle) scrap->runs);
  186.                     
  187.                     size = scrap->numRuns * sizeof(NewRunRec);
  188.                     SetHandleSize((Handle) scrap->runs, size);
  189.                     
  190.                     HLock((Handle) scrap->runs);
  191.                     
  192.                     size = (scrap->numRuns - runIndex - 1) * sizeof(NewRunRec);
  193.                     BlockMove((Ptr) (*scrap->runs + runIndex), (Ptr) (*scrap->runs + runIndex + 1), size);
  194.                     
  195.                     NewNewRun(dp, *scrap->runs + runIndex, styleIndex);
  196.                     
  197.                     runOffset = 0;
  198.                     
  199.                 } else {
  200.                 
  201.                     scrap->numRuns += 2;
  202.                     
  203.                     HUnlock((Handle) scrap->runs);
  204.                     
  205.                     size = scrap->numRuns * sizeof(NewRunRec);
  206.                     SetHandleSize((Handle) scrap->runs, size);
  207.                     
  208.                     HLock((Handle) scrap->runs);
  209.                     
  210.                     size = (scrap->numRuns - runIndex - 3) * sizeof(NewRunRec);
  211.                     BlockMove((Ptr) (*scrap->runs + runIndex + 1), (Ptr) (*scrap->runs + runIndex + 3), size);
  212.                     
  213.                     SplitNewRun(dp, *scrap->runs + runIndex, runOffset, *scrap->runs + runIndex + 2);
  214.                     
  215.                     NewNewRun(dp, *scrap->runs + runIndex + 1, styleIndex);
  216.                     
  217.                     runIndex++;
  218.                     runOffset = 0;
  219.                     
  220.                 }
  221.                 
  222.                 rp = *scrap->runs + runIndex;
  223.                 
  224.                 /* just set up the run -- don't worry about the text data */
  225.                 
  226.                 rp->numText = sizeof(short);
  227.                 SetHandleSize((Handle) rp->text, rp->numText);
  228.                                 
  229.             }
  230.             
  231.             replace->replaceIndex = replaceIndex;
  232.             replace->runIndex = runIndex;
  233.             replace->runOffset = runOffset;
  234.                 
  235.             HUnlock((Handle) scrap->runs);
  236.                 
  237.             return(true);
  238.                 
  239.         }
  240.  
  241.     HUnlock((Handle) scrap->runs);
  242.     
  243.     return(false);
  244.     
  245. }
  246.  
  247. static Boolean FindStrInRun(ReplacementPtr replacements, Str255 str, NewRunPtr rp, short * runOffset)
  248. {
  249.     short        maxOffset;
  250.     short        strLen;
  251.     char            * strPtr, * textPtr;
  252.     short        i;
  253.     StylePtr        style;
  254.     
  255.     /* make sure the run is in the correct platform, script and encoding.
  256.          WHY?  Because we are looking for ASCII sctrings which don't make sense if these
  257.          values are not set correctly  */
  258.     
  259.     style = GetDocStyle(replacements->dp, rp->styleIndex);
  260.     
  261.     if(style->platform != gxMacintoshPlatform)
  262.         return(false);
  263.             
  264.     /* lets look for it */
  265.             
  266.     strLen = str[0];
  267.     maxOffset = rp->numText - strLen;
  268.     
  269.     strPtr = (char *) &str[1];
  270.     textPtr = (char *) *rp->text;
  271.     
  272.     for(*runOffset = 0; *runOffset <= maxOffset; (*runOffset)++, textPtr++) {
  273.     
  274.         for(i=0; i<strLen; i++)
  275.             if(strPtr[i] != textPtr[i])
  276.                 break;
  277.                 
  278.         if(i == strLen)
  279.             return(true);
  280.             
  281.     }
  282.     
  283.     return(false);
  284.     
  285. }
  286.  
  287. static void DoReplace(ReplacementPtr replacements, ReplacePtr replace)
  288. {
  289.     NewRunPtr        rp;
  290.     char                * charPtr;
  291.     short            * shortPtr;
  292.     
  293.     rp = *replacements->dp->scrap.runs + replace->runIndex;
  294.     
  295.     if(!replacements->proof->glyphIndicies) {
  296.         charPtr = (char *) *rp->text + replace->runOffset;
  297.         *charPtr = replacements->curChar[replace->replaceIndex];
  298.     } else {
  299.         shortPtr = (short *) ((char *) *rp->text + replace->runOffset);
  300.         *shortPtr = replacements->curChar[replace->replaceIndex];
  301.     }
  302. }
  303.  
  304.